# -*- coding: utf-8 -*-
"""
Python3 错误和异常处理详解

核心概念：
1. 语法错误(Syntax Errors) : 解释器无法解析的错误
2. 异常(Exceptions)       : 运行时检测到的错误
3. 异常处理机制          : try/except/finally/raise
"""

# ======================
# 1. 基础异常处理
# ======================
try:
    # 可能引发异常的代码
    num = int(input("请输入数字: "))
    result = 10 / num
except ValueError:
    print("输入的不是有效数字！")
except ZeroDivisionError:
    print("不能除以零！")
else:
    print(f"计算结果: {result}")
finally:
    print("执行结束")  # 无论是否异常都会执行

# ======================
# 2. 常见异常类型
# ======================
# 2.1 基础异常
try:
    # IndexError
    lst = [1, 2, 3]
    print(lst[5])

    # KeyError
    d = {'a': 1}
    print(d['b'])

    # TypeError
    '2' + 2

except (IndexError, KeyError) as e:
    print(f"集合类错误: {type(e).__name__}")

# 2.2 高级异常处理
try:
    with open("不存在的文件.txt") as f:
        content = f.read()
except FileNotFoundError as e:
    print(f"文件错误: {e.strerror}")  # 输出: 文件错误: No such file or directory


# ======================
# 3. 自定义异常
# ======================
class AgeError(Exception):
    """自定义年龄异常"""

    def __init__(self, age, message="年龄必须在0-150之间"):
        self.age = age
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f"{self.age} -> {self.message}"


def check_age(age):
    if not 0 <= age <= 150:
        raise AgeError(age)
    return age


try:
    check_age(200)
except AgeError as e:
    print(e)  # 输出: 200 -> 年龄必须在0-150之间

# ======================
# 4. 高级异常处理技巧
# ======================
# 4.1 异常链（Python 3.11+）
try:
    raise ValueError("原始错误")
except Exception as e:
    raise RuntimeError("新错误") from e

# 4.2 异常组（Python 3.11+）
try:
    raise ExceptionGroup("多错误组", [
        ValueError(1),
        TypeError(2),
        OSError(3)
    ])
except* ValueError:
    print("处理ValueError")
except* OSError:
    print("处理OSError")


# 4.3 上下文管理器（自动资源管理）
class DatabaseConnection:
    def __enter__(self):
        print("建立数据库连接")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("关闭数据库连接")
        if exc_type:
            print(f"发生错误: {exc_val}")


with DatabaseConnection() as conn:
    print("执行数据库操作")
    # raise Exception("模拟数据库错误")

# ======================
# 5. 调试和日志
# ======================
import logging
import traceback

# 配置日志
logging.basicConfig(filename='error.log', level=logging.ERROR)

try:
    1 / 0
except Exception as e:
    logging.error(f"发生错误: {str(e)}")
    logging.error(traceback.format_exc())  # 记录完整堆栈信息
